package com.common.www.utils;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;


public class FileUtils {


    public FileUtils() {
        super();
    }

    /**
     * 删除文件夹
     *
     * @param deleteThisPath 把本文件夹也删除掉(删除掉文件夹)
     */
    public static void deleteDir(String filePath, boolean deleteThisPath) {
        if (!TxtUtil.isEmpty(filePath)) {
            File file = new File(filePath);

            if (file.isDirectory()) {// 处理目录
                File files[] = file.listFiles();
                for (int i = 0; i < files.length; i++) {
                    deleteDir(files[i].getAbsolutePath(), deleteThisPath);
                }
            }
            if (!file.isDirectory()) {// 如果是文件，删除
                file.delete();
            } else {// 目录,不删除
                if (deleteThisPath) {
                    if (file.listFiles().length == 0) {// 目录下没有文件或者目录，删除
                        file.delete();
                    }
                }

            }
        }
    }

    /**
     * 删除文件
     */
    public static void deleteFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            file.delete();
        }
    }

    /**
     * 判断文件是否存在
     *
     * @param filePath 文件的路径
     */
    public static boolean isFileExists(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            return true;
        } else {
            return false;
        }
    }


    /**
     * 调用此方法自动计算指定文件或指定文件夹的大小
     *
     * @param filePath 文件路径
     * @return 计算好的带B、KB、MB、GB的字符串
     */
    public static String getAutoFileOrFilesSize(String filePath) {
        File file = new File(filePath);
        long blockSize = 0;
        try {
            if (file.isDirectory()) {
                blockSize = getDirSize(file.getAbsolutePath());
            } else {
                blockSize = getFileSize(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return formatFileSize(blockSize);
    }


    /**
     * get file size
     * <ul>
     * <li>if path is null or empty, return 0</li>
     * <li>if path exist and it is a file, return file size, else return 0</li>
     * <ul>
     *
     * @return returns the length of this file in bytes. returns -1 if the file does not exist.
     */
    public static long getFileSize(File file) {
        if (TxtUtil.isEmpty(file.getAbsolutePath())) {
            return 0;
        }
        return (file.exists() && file.isFile() ? file.length() : -1);
    }

    /**
     * get file size
     * <ul>
     * <li>if path is null or empty, return 0</li>
     * <li>if path exist and it is a file, return file size, else return 0</li>
     * <ul>
     *
     * @return returns the length of this file in bytes. returns -1 if the file does not exist.
     */
    public static long getFileSize(String path) {
        if (TxtUtil.isEmpty(path)) {
            return 0;
        }
        File file = new File(path);
        return (file.exists() && file.isFile() ? file.length() : -1);
    }

    /**
     * 获取指定文件夹大小
     *
     * @param path
     * @return
     * @throws Exception
     */
    public static long getDirSize(String path) throws Exception {
        File f = new File(path);
        long size = 0;
        File flist[] = f.listFiles();
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getDirSize(flist[i].getAbsolutePath());
            } else {
                size = size + getFileSize(flist[i]);
            }
        }
        return size;
    }

    /**
     * 获取文件个数 **
     */
    public static long getFileNums(File f) {// 递归求取目录文件个数
        long size = 0;
        File flist[] = f.listFiles();
        size = flist.length;
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getFileNums(flist[i]);
                size--;
            }
        }
        return size;
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String formatFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String formatFileSize(String fileS) {
        long size = 0;
        try {
            size = Long.parseLong(fileS);
        } catch (Exception e) {

        }
        return formatFileSize(size);
    }


    /**
     * 小转换，之转换到MB
     */
    public static String formatFileSize2(long filesize) {
        String strUnit = "Bytes";
        String strAfterComma = "";
        int intDivisor = 1;
        if (filesize >= 1024 * 1024) {
            strUnit = "MB";
            intDivisor = 1024 * 1024;
        } else if (filesize >= 1024) {
            strUnit = "KB";
            intDivisor = 1024;
        }
        if (intDivisor == 1)
            return filesize + " " + strUnit;
        strAfterComma = "" + 100 * (filesize % intDivisor) / intDivisor;
        if (strAfterComma == "")
            strAfterComma = ".0";
        return filesize / intDivisor + "." + strAfterComma + " " + strUnit;
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String FormetFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    /**
     * 得到文件名的后缀
     */
    public static String getSuffix(String nameOrPath) {
        if (nameOrPath == null)
            return "";
        return nameOrPath.substring(nameOrPath.lastIndexOf(".") + 1, nameOrPath.length());
    }

    /**
     * 得到文件名
     */
    public static String getFileNameByPath(String path) {
        if (path == null)
            return "";
        return path.substring(path.lastIndexOf("/") + 1, path.length());
    }

    /**
     * 得到文件名，不带后缀
     */
    public static String getFileNameWithoutSuffix(String pathOrName) {
        if (pathOrName == null)
            return "";
        if (pathOrName.lastIndexOf(".") > 0) {
            return pathOrName.substring(0, pathOrName.lastIndexOf("."));
        } else {
            return pathOrName;
        }
    }

    /**
     * 复制单个文件
     *
     * @param oldPath String 原文件路径 如：c:/fqf.txt
     * @param newPath String 复制后路径 如：f:/fqf.txt
     * @return boolean
     */
    public static void copyFile(String oldPath, String newPath) {
        try {
            int bytesum = 0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) { //文件存在时
                InputStream inStream = new FileInputStream(oldPath); //读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
                int length;
                while ((byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; //字节数 文件大小
//                    System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();
        }
    }

    /**
     * 复制目录
     *
     * @param fromDir
     * @param toDir
     * @param ignores 忽略的文件或文件夹
     * @throws IOException
     */
    public static void copyDir(String fromDir, String toDir, String... ignores) throws IOException {
        //创建目录的File对象
        File dirSouce = new File(fromDir);
        //判断源目录是不是一个目录
        if (!dirSouce.isDirectory()) {
            //如果不是目录那就不复制
            return;
        }
        //创建目标目录的File对象
        File destDir = new File(toDir);
        //如果目的目录不存在
        if (!destDir.exists()) {
            //创建目的目录
            destDir.mkdir();
        }
        //获取源目录下的File对象列表
        File[] files = dirSouce.listFiles();
        for (File file : files) {

            boolean jump = false;//判断是否是忽略的文件
            if (ignores != null)
                for (int j = 0; j < ignores.length; j++) {
                    if (ignores[j].equals(file.getName())) {//是忽略文件
                        jump = true;
                        break;
                    }
                }
            if (jump) {
                continue;
            }

            //拼接新的fromDir(fromFile)和toDir(toFile)的路径
            String strFrom = fromDir + File.separator + file.getName();
//            System.out.println(strFrom);
            String strTo = toDir + File.separator + file.getName();
//            System.out.println(strTo);
            //判断File对象是目录还是文件
            //判断是否是目录
            if (file.isDirectory()) {
                //递归调用复制目录的方法
                copyDir(strFrom, strTo);
            }
            //判断是否是文件
            if (file.isFile()) {
                System.out.println("正在复制文件：" + file.getName());
                //递归调用复制文件的方法
                copyFile(strFrom, strTo);
            }
        }
    }


    private ArrayList<File> scanFiles = new ArrayList<>();

    /**
     * TODO:递归扫描指定文件夹下面的指定文件
     *
     * @param ignores 忽略的文件或文件夹
     * @return ArrayList<Object>
     * @throws FileNotFoundException
     */
    public void scanFiles(String folderPath, onScanFilesListener listener, String... ignores) throws FileNotFoundException {
        File directory = new File(folderPath);
        if (!directory.isDirectory()) {
            throw new FileNotFoundException('"' + folderPath + '"' + " input path is not a Directory , please input the right path of the Directory. ^_^...^_^");
        }
        File[] filelist = directory.listFiles();
        for (int i = 0; i < filelist.length; i++) {
            boolean jump = false;//判断是否是忽略的文件
            if (ignores != null)
                for (int j = 0; j < ignores.length; j++) {
                    if (ignores[j].equals(filelist[i].getName())) {//是忽略文件
                        jump = true;
                        break;
                    }
                }
            if (jump) {
                continue;
            }

            /**如果当前是文件夹，进入递归扫描文件夹**/
            if (filelist[i].isDirectory()) {
                /**递归扫描下面的文件夹**/
                scanFiles(filelist[i].getAbsolutePath(), listener, ignores);
            }
            /**非文件夹**/
            else {
                scanFiles.add(filelist[i]);
                if (listener != null) {
                    listener.onScan(filelist[i], scanFiles);
                }
//                    System.out.println(filelist[i].getAbsolutePath());
            }
        }
    }


    public interface onScanFilesListener {
        /**
         * @param file      当前扫描出的文件
         * @param scanFiles 总共扫描出的文件
         */
        void onScan(File file, ArrayList<File> scanFiles);
    }


    /**
     * 文件是否在占用中
     */
    public static boolean isInUse(File file) {
        if (file.renameTo(file)) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 图片后缀表
     */
    private static List<String> imgSuffixList = new ArrayList<>();
    private static List<String> gifSuffixList = new ArrayList<>();
    private static List<String> videoSuffixList = new ArrayList<>();

    public static List<String> getImgSuffixList() {
        initSuffixList();//装载后缀列表
        return imgSuffixList;
    }

    public static List<String> getGifSuffixList() {
        initSuffixList();//装载后缀列表
        return imgSuffixList;
    }

    public static List<String> getVideoSuffixList() {
        initSuffixList();//装载后缀列表
        return videoSuffixList;
    }

    public static void initSuffixList() {
        if (imgSuffixList == null)
            imgSuffixList = new ArrayList<>();
        if (gifSuffixList == null)
            gifSuffixList = new ArrayList<>();
        if (videoSuffixList == null)
            videoSuffixList = new ArrayList<>();

        if (imgSuffixList.size() == 0) {
            imgSuffixList.add(".png");
            imgSuffixList.add(".jpg");
            imgSuffixList.add(".jpeg");
            imgSuffixList.add(".bmp");
            imgSuffixList.add(".tif");

            List<String> list = new ArrayList<>();
            for (int i = 0; i < imgSuffixList.size(); i++) {//添加所有大写后缀
                list.add(imgSuffixList.get(i).toUpperCase());
            }

            imgSuffixList.addAll(list);
        }
        if (gifSuffixList.size() == 0) {
            gifSuffixList.add(".gif");

            List<String> list = new ArrayList<>();
            for (int i = 0; i < gifSuffixList.size(); i++) {//添加所有大写后缀
                list.add(gifSuffixList.get(i).toUpperCase());
            }

            gifSuffixList.addAll(list);
        }
        if (videoSuffixList.size() == 0) {
            videoSuffixList.add(".avi");
            videoSuffixList.add(".wmv");
            videoSuffixList.add(".mpeg");
            videoSuffixList.add(".m4v");
            videoSuffixList.add(".mov");
            videoSuffixList.add(".asf");
            videoSuffixList.add(".flv");
            videoSuffixList.add(".f4v");
            videoSuffixList.add(".rmvb");
            videoSuffixList.add(".rm");
            videoSuffixList.add(".3gp");
            videoSuffixList.add(".vob");

            List<String> list = new ArrayList<>();
            for (int i = 0; i < videoSuffixList.size(); i++) {//添加所有大写后缀
                list.add(videoSuffixList.get(i).toUpperCase());
            }

            videoSuffixList.addAll(list);
        }

    }

    /**
     * 是否是图片文件
     */
    public static boolean isImgFile(String fileOrUrl) {
        if (fileOrUrl == null)
            return false;
        initSuffixList();//装载后缀列表
        for (int i = 0; i < imgSuffixList.size(); i++) {
            if (fileOrUrl.contains(imgSuffixList.get(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否是文件
     */
    public static boolean isGifFile(String fileOrUrl) {
        if (fileOrUrl == null)
            return false;
        initSuffixList();//装载后缀列表
        for (int i = 0; i < gifSuffixList.size(); i++) {
            if (fileOrUrl.contains(gifSuffixList.get(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否是文件
     */
    public static boolean isVideoFile(String fileOrUrl) {
        if (fileOrUrl == null)
            return false;
        initSuffixList();//装载后缀列表
        for (int i = 0; i < videoSuffixList.size(); i++) {
            if (fileOrUrl.contains(videoSuffixList.get(i))) {
                return true;
            }
        }
        return false;
    }


    /**
     * 第二种
     * 追加文件：使用FileWriter
     *
     * @param filePath
     * @param content
     */
    public static void writeFile(String filePath, String content) {
        try {
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
//            FileWriter writer = new FileWriter(filePath, true);
//            writer.write(content);
//            writer.close();
            FileOutputStream fos = new FileOutputStream(filePath);
            OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
            osw.write(content);
            osw.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 读取文件内容
     */
    public static String readFileContent(String filePath) throws IOException {

        // 读取文件内容到Stream流中，按行读取
        Stream<String> lines = Files.lines(Paths.get(filePath));

        StringBuilder builder = new StringBuilder();
        // 随机行顺序进行数据处理
        lines.forEach(ele -> {
//            System.out.println(ele);
            builder.append(ele);
        });
        return builder.toString();

    }

}
